package com.haizhi.crm.sys.auth.service.impl;

import com.haizhi.crm.common.constant.SysStatus;
import com.haizhi.crm.common.exception.UnexpectedStatusException;
import com.haizhi.crm.common.log.GLog;
import com.haizhi.crm.common.log.LogFactory;
import com.haizhi.crm.common.model.Response;
import com.haizhi.crm.sys.auth.dao.PositionDao;
import com.haizhi.crm.sys.auth.dao.PositionRoleDao;
import com.haizhi.crm.sys.auth.dao.ResourceDao;
import com.haizhi.crm.sys.auth.dao.RoleResourcePermissionDao;
import com.haizhi.crm.sys.auth.model.*;
import com.haizhi.crm.sys.auth.service.PositionPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * Created by yangyijun on 2018/5/17.
 */
@Transactional
@Service
public class PositionPermissionServiceImpl implements PositionPermissionService {

    private static final GLog LOG = LogFactory.getLogger(PositionPermissionServiceImpl.class);

    @Autowired
    private RoleResourcePermissionDao roleResourcePermissionDao;
    @Autowired
    private PositionRoleDao positionRoleDao;
    @Autowired
    private PositionDao positionDao;
    @Autowired
    private ResourceDao resourceDao;


    @Override
    public Response save(PositionResourceQo prQo) {
        persist(prQo);
        return Response.success();
    }

    @Override
    public Response update(PositionResourceQo prpQo) {
        try {
            del(prpQo.getPositionId());
            save(prpQo);
        } catch (Exception e) {
            LOG.error("update position permission error", e);
            throw new UnexpectedStatusException(SysStatus.UPDATE_POSITION_PERMISSION_ERROR, e, prpQo.getPositionId());
        }
        return Response.success();
    }

    @Override
    public Response delete(Long positionId) {
        try {
            List<ResourceVo> resourceVos = resourceDao.findByPositionId(positionId);
            if (CollectionUtils.isEmpty(resourceVos)) {
                throw new UnexpectedStatusException(SysStatus.POSITION_NOT_EXISTS_PERMISSION_ERROR);
            }
            del(positionId);
            LOG.info("position {0} permission deleted", positionId);
        } catch (UnexpectedStatusException e) {
            throw new UnexpectedStatusException(e.getStatus(), e, positionId);
        } catch (Exception e) {
            LOG.error("delete position permission error", e);
            throw new UnexpectedStatusException(SysStatus.DELETE_POSITION_PERMISSION_ERROR, e, positionId);
        }
        return Response.success();
    }

    @Override
    public Response list() {
        try {
            List<PositionResourceVo> positionResourceVos = new ArrayList<>();
            List<PositionVo> positionVos = positionDao.list();
            for (PositionVo positionVo : positionVos) {
                positionResourceVos.add(buildPositionResources(positionVo.getId(), positionVo.getName()));
            }
            return Response.success(positionResourceVos);
        } catch (Exception e) {
            LOG.error("search position permission list error", e);
            throw new UnexpectedStatusException(SysStatus.LIST_POSITION_PERMISSION_ERROR, e, null);
        }
    }

    @Override
    public Response detail(Long positionId) {
        try {
            PositionDo positionDo = positionDao.findOne(positionId);
            PositionResourceVo prVo = buildPositionResources(positionDo.getId(), positionDo.getName());
            return Response.success(prVo);
        } catch (Exception e) {
            LOG.error("search position permission detail error", e);
            throw new UnexpectedStatusException(SysStatus.DETAIL_POSITION_PERMISSION_ERROR, e, positionId);
        }
    }

    ///////////////////////
    // private functions
    ///////////////////////

    private void persist(PositionResourceQo prQo) {
        Long positionId = prQo.getPositionId();
        try {
            List<PositionRoleDo> positionRoles = getPositionRoleDos(positionId);
            Long[] resourceIds = prQo.getResourceIds();
            List<RoleResourcePermissionDo> rrpDoList = new LinkedList<>();
            List<Long> roleIds = new LinkedList<>();

            List<Long> allResourceIds = resourceDao.findIds();
            allResourceIds.removeAll(Arrays.asList(resourceIds));

            for (PositionRoleDo pr : positionRoles) {
                buildRoleResourcePermission(resourceIds, rrpDoList, pr, "true" );
                buildRoleResourcePermission(allResourceIds.toArray(new Long[allResourceIds.size()]), rrpDoList, pr, "false" );
                roleIds.add(pr.getRoleId());
                pr.setUpdatedDt(new Date());
            }
            Integer rrpCount = roleResourcePermissionDao.findByRoleIds(roleIds.toArray(new Long[roleIds.size()]));
            if (null == rrpCount || rrpCount == 0) {
                roleResourcePermissionDao.save(rrpDoList);
                positionRoleDao.save(positionRoles);
            } else {
                LOG.error("岗位ID【{0}】已经添加过权限，只能进行修改，不能再进行添加操作", positionId);
                throw new UnexpectedStatusException(SysStatus.HAD_POSITION_PERMISSION_ERROR);
            }
        } catch (UnexpectedStatusException e) {
            throw new UnexpectedStatusException(e.getStatus(), e, positionId);
        } catch (Exception e) {
            throw new UnexpectedStatusException(SysStatus.SAVE_POSITION_PERMISSION_ERROR, e, positionId);
        }
    }

    private void buildRoleResourcePermission(Long[] resourceIds, List<RoleResourcePermissionDo> rrpDoList, PositionRoleDo pr, String checked) {
        for (Long resourceId : resourceIds) {
            RoleResourcePermissionDo rrpDo = new RoleResourcePermissionDo();
            rrpDo.setRoleId(pr.getRoleId());
            rrpDo.setResourceId(resourceId);
            rrpDo.setPermissionId(1l);
            rrpDo.setChecked(checked);
            rrpDoList.add(rrpDo);
        }
    }

    private PositionResourceVo buildPositionResources(Long positionId, String positionName) throws Exception {
        PositionRoleDo positionRoleDo = getPositionRoleDos(positionId).get(0);
        List<ResourceVo> resourceVos = ResourceVo.buildResourceTree(resourceDao.findByPositionId(positionId));
        PositionResourceVo prVo = new PositionResourceVo();
        prVo.setUpdateDt(positionRoleDo.getUpdatedDt());
        prVo.setPositionId(positionId);
        prVo.setPositionName(positionName);
        prVo.setResourceVos(resourceVos);
        return prVo;
    }


    private void del(Long positionId) throws Exception {
        List<PositionRoleDo> positionRoles = getPositionRoleDos(positionId);
        List<Long> roleIds = new LinkedList<>();
        for (PositionRoleDo positionRoleDo : positionRoles) {
            roleIds.add(positionRoleDo.getRoleId());
        }
        roleResourcePermissionDao.deleteByRoleIds(roleIds.toArray(new Long[roleIds.size()]));
    }

    private List<PositionRoleDo> getPositionRoleDos(Long positionId) throws Exception {
        List<PositionRoleDo> positionRoles = positionRoleDao.findByPositionId(positionId);
        if (CollectionUtils.isEmpty(positionRoles)) {
            LOG.error("岗位ID【{0}】不存在", positionId);
            throw new Exception("岗位不存在" );
        }
        return positionRoles;
    }
}
